package net.nshc.kwkim.mycalc.temp;

public class Token {
	// Names for different kinds of Operators.
	// Java has no enum types, so we use final ints.
	public static final int CLOSE_PAR = 1; 
	public static final int OPEN_PAR = 2; 
	public static final int BEGIN = 3; 
	public static final int END = 4; 
	public static final int ADD = 5; 
	public static final int SUBTRACT = 6; 
	public static final int MULTIPLY = 7; 
	public static final int DIVIDE = 8; 
	public static final int POWER = 9; 

	// Names for kinds of associativity.
	public static final int LEFT = 100;
	public static final int RIGHT = 101;

	// Ctor.  Example uses:
	//   new Token(true, 42);         // create new token containing number 42
	//   new Token(false, Token.ADD); // create new token containing operator ADD
	public Token(boolean isNumberArg, int numberOrOperatorArg)
	{
		isNumberF = isNumberArg;
		numberOrOperatorF = numberOrOperatorArg;
	}  

	public boolean isNumber()
	{
		return isNumberF;
	}

	public boolean isOperator()
	{
		return !isNumberF;
	}

	public int value()
	{
		return numberOrOperatorF;
	}

	public int kindOfOperator()
	{
		return numberOrOperatorF;
	}

	public int precedence()
	{

		int result = -1;
		switch (numberOrOperatorF) {
		case OPEN_PAR:
		case CLOSE_PAR:
		case BEGIN:
		case END:
			result = 0; break;
		case ADD:
		case SUBTRACT:
			result = 1; break;
		case MULTIPLY:
		case DIVIDE:
			result = 2; break;
		case POWER:
			result = 3; break;
		}
		return result;
	}

	public int associativity()
	{

		int result = -1;
		switch (numberOrOperatorF) {
		case OPEN_PAR:
		case CLOSE_PAR:
		case BEGIN:
		case END:
		case POWER:
			result = RIGHT; break;
		case ADD:
		case SUBTRACT:
		case MULTIPLY:
		case DIVIDE:
			result = LEFT; break;
		}
		return result;
	}

	public String toString()
	{
		String result = null;
		if (isNumberF)
			result = String.valueOf(numberOrOperatorF);
		else
			switch (numberOrOperatorF) {
			case BEGIN:
				result = "BEGIN"; break;
			case OPEN_PAR:
				result = "(" ; break;
				case CLOSE_PAR:
					result = ")" ; break;
			case ADD:
				result = "+" ; break;
			case SUBTRACT:
				result = "-" ; break;
			case MULTIPLY:
				result = "*" ; break;
			case DIVIDE:
				result = "/" ; break;
			case POWER:
				result = "^" ; break;
			case END:
				result = "END"; break;
			}
		return result;
	}

	public static boolean preferLeft(Token left, Token right)
	{

		boolean result = false;      
		if (left.precedence() > right.precedence())
			result = true;
		else if (left.precedence() == right.precedence()
				&& left.associativity() == LEFT)
			result = true;
		return result;
	}

	private boolean isNumberF;     // true for numbers, false for operators
	private int numberOrOperatorF; // number or something in CLOSE_PAR ... BEGIN
}
